﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.DirectX;
using System.Drawing;

namespace MedicWave.Visualization3d
{
    struct InternalScatterplotPoint
    {
        public Vector3 Position;

        public string CaseName;
        bool ShowLabel;

        public InternalScatterplotClass caseClass;

    }

    class InternalScatterplotClass
    {
        string className;

        public string ClassName
        {
            get { return className; }
            set { className = value; }
        }
        Color classColor;

        public Color ClassColor
        {
            get { return classColor; }
            set { classColor = value; }
        }

    }

    class InternalScatterplotData
    {
        static Color[] collorsArray = {Color.Blue, Color.Red, Color.Green, Color.Yellow, Color.Violet,
                                       Color.White, Color.Aqua, Color.Cyan, Color.Orange, Color.Olive,
                                       Color.PapayaWhip, Color.Purple, Color.Silver, Color.Tomato, Color.Tomato,
                                       Color.Thistle, Color.SpringGreen, Color.Snow, Color.Salmon, Color.Peru};

        ScatterplotType plotType;

        public ScatterplotType PlotType
        {
            get { return plotType; }
            set { plotType = value; }
        }

        ScatterplotSettings settings;

        public ScatterplotSettings Settings
        {
            get { return settings; }
            set { settings = value; }
        }
        List<InternalScatterplotPoint> plotData;

        public List<InternalScatterplotPoint> PlotData
        {
            get { return plotData; }
        }

        List<InternalScatterplotClass> plotClasses;

        public List<InternalScatterplotClass> PlotClasses
        {
            get { return plotClasses; }
            set { plotClasses = value; }
        }


        float minX;

        public float MinX
        {
            get { return minX; }
        }
        float maxX;

        public float MaxX
        {
            get { return maxX; }
        }


        float minY;

        public float MinY
        {
            get { return minY; }
        }
        float maxY;

        public float MaxY
        {
            get { return maxY; }
        }
        float minZ;

        public float MinZ
        {
            get { return minZ; }
        }
        float maxZ;

        public float MaxZ
        {
            get { return maxZ; }
        }
        public float XRange
        {
            get { return maxX - minX; }
        }
        public float YRange
        {
            get { return maxY - minY; }
        }
        public float ZRange
        {
            get { return maxZ - minZ; }
        }



        internal static InternalScatterplotData FromRawData(ScatterplotData plotData)
        {
            InternalScatterplotData newData = new InternalScatterplotData();
            newData.plotType = plotData.PlotType;

            //prepare classes
            uint nClasses = 0;
            for (int i = 0; i < plotData.CasesClassLabels.Count; i++)
            {
                if (plotData.CasesClassLabels[i] + 1 > nClasses)
                    nClasses = plotData.CasesClassLabels[i] + 1;

            }
            newData.plotData = new List<InternalScatterplotPoint>();
            newData.plotClasses = new List<InternalScatterplotClass>();

            for (int i = 0; i < nClasses; i++)
            {
                InternalScatterplotClass scatterplotClass = new InternalScatterplotClass();
                if (plotData.ClassNames != null && plotData.ClassNames.Count > i)
                    scatterplotClass.ClassName = plotData.ClassNames[i];
                //else if(i==0)
                //    scatterplotClass.ClassName = "Class";
                //else if (i == 1)
                //    scatterplotClass.ClassName = "Cancer";
                else
                    scatterplotClass.ClassName = "Class" + (i + 1).ToString();
                if (i < 20)
                    scatterplotClass.ClassColor = collorsArray[i];
                else
                {
                    Random rnd = new Random();
                    scatterplotClass.ClassColor = Color.FromArgb(rnd.Next(256),rnd.Next(256), rnd.Next(256));
                }
                newData.plotClasses.Add(scatterplotClass);
            }

            for (int i = 0; i < plotData.PlotData.Count; i++)
            {
                InternalScatterplotPoint point = new InternalScatterplotPoint();

                point.Position.X = plotData.PlotData[i].X;
                point.Position.Y = plotData.PlotData[i].Y;
                point.Position.Z = plotData.PlotData[i].Z;

                if (point.Position.X < newData.minX || i==0)
                    newData.minX = point.Position.X;
                if (point.Position.X > newData.maxX || i == 0)
                    newData.maxX = point.Position.X;

                if (point.Position.Y < newData.minY || i == 0)
                    newData.minY = point.Position.Y;
                if (point.Position.Y > newData.maxY || i == 0)
                    newData.maxY = point.Position.Y;


                if (point.Position.Z < newData.minZ || i == 0)
                    newData.minZ = point.Position.Z;
                if (point.Position.Z > newData.maxZ || i == 0)
                    newData.maxZ = point.Position.Z;



                if (plotData.ShowCaseNames != null && plotData.ShowCaseNames.Count > i && plotData.ShowCaseNames[i] && plotData.CaseNames != null && plotData.CaseNames.Count > i)
                    point.CaseName = plotData.CaseNames[i];
                else if(plotData.ShowCaseNames==null && plotData.CaseNames!=null &&plotData.CaseNames.Count > i)
                    point.CaseName = plotData.CaseNames[i];
                else
                    point.CaseName = null;

                if (plotData.CasesClassLabels != null && plotData.CasesClassLabels.Count > i)
                    point.caseClass = newData.PlotClasses[(int)plotData.CasesClassLabels[i]];
                else
                    point.caseClass = null;

                newData.plotData.Add(point);
            }

            newData.settings.Reset();
            return newData;
        }

    }
}
